package com.ylr.base.common.utils;

import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2023-04-16 17:05:57
 * className: Sha256Utils
 * version: 1.0
 * description:
 */
public class Sha256Utils {

    private static final Logger log = LoggerFactory.getLogger(Sha256Utils.class);

    /**
     * Sha256加密
     * @param plainText 明文
     * @return 密文
     */
    public static String encodeSha256(String plainText) {
        if (StringUtils.isBlank(plainText)) {
            log.error("Sha256加密参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doEncodeSha256(plainText, StringUtils.EMPTY, false);
    }

    /**
     * Sha256加密
     * @param plainText 明文
     * @param secretKey 密钥
     * @return 密文
     */
    public static String encodeSha256(String plainText, String secretKey) {
        if (StringUtils.isAnyBlank(plainText, secretKey)) {
            log.error("Sha256加密参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doEncodeSha256(plainText, secretKey, false);
    }

    /**
     * Sha256加密
     * @param plainText 明文
     * @param toUpper   十六进制值大写
     * @return 密文
     */
    public static String encodeSha256(String plainText, boolean toUpper) {
        if (StringUtils.isBlank(plainText)) {
            log.error("Sha256加密参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doEncodeSha256(plainText, StringUtils.EMPTY, toUpper);
    }

    /**
     * Sha256加密
     * @param plainText 明文
     * @param secretKey 密钥
     * @param toUpper   十六进制值大写
     * @return 密文
     */
    public static String encodeSha256(String plainText, String secretKey, boolean toUpper) {
        if (StringUtils.isAnyBlank(plainText, secretKey)) {
            log.error("Sha256加密参数为空");
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
        return doEncodeSha256(plainText, secretKey, toUpper);
    }

    /**
     * 执行Sha256加密
     * @param plainText 明文
     * @param secretKey 密钥
     * @param toUpper   密文转大写
     * @return 密文
     */
    private static String doEncodeSha256(String plainText, String secretKey, boolean toUpper) {
        byte[] bytes = plainText.getBytes(StandardCharsets.UTF_8);
        if (StringUtils.isNotEmpty(secretKey)) {
            byte[] plainTextBytes = bytes;
            byte[] secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8);
            bytes = new byte[plainTextBytes.length + secretKeyBytes.length];

            int middleIndex = secretKeyBytes.length >>> 1;
            int index = 0;
            if (middleIndex > 0) {
                // 密钥字节数组复制
                System.arraycopy(secretKeyBytes, 0, bytes, index, middleIndex);
                // 下标变更
                index += middleIndex;
            }
            // 明文字节数组复制
            System.arraycopy(plainTextBytes, 0, bytes, index, plainTextBytes.length);
            // 下标变更
            index += plainTextBytes.length;
            // 密钥字节数组复制
            System.arraycopy(secretKeyBytes, middleIndex, bytes, index, secretKeyBytes.length - middleIndex);
        }
        try {
            // 获取加密对象
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            // sha256加密并返回十六进制数值
            return ByteUtils.bytesToHex(messageDigest.digest(bytes), toUpper);
        } catch (NoSuchAlgorithmException e) {
            log.error("Sha256加密异常，加密算法不存在。message={}", e.getMessage(), e);
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        } catch (Exception e) {
            log.error("Sha256加密异常。message={}", e.getMessage(), e);
            throw new YlrException(ResultEnum.SERVICE_FAIL);
        }
    }

}
